//
//  KKBaseAFNetWorking.m
//  AFnetWorking测试
//
//  Created by long on 14-11-18.
//  Copyright (c) 2014年 谭启龙. All rights reserved.
//

#import "XLBaseAFNetWorking.h"
#import "AFNetworking.h"
#import "CMCometNetWorking.h"
#import <objc/runtime.h>
#import "XLDataBaseManager.h"

@interface XLBaseAFNetWorking ()
{

    AFHTTPSessionManager * _netManager;
    UIActivityIndicatorView * _activityView;
    NSURLSessionDataTask * _dataTask;
}
@end

@implementation XLBaseAFNetWorking
- (NSString*)getRequestUrl
{
    return self.requestUrl;
}

//网络加载的方法 --需要子类重写
- (XLRequestMethod)getRequestMethod
{
    return XLRequestMethodGet;
}

#pragma mark --普通网络连接
//初始化并网络加载
-(id)initWithParameters:(NSMutableDictionary *)dic IndicatorView:(UIView *)view LoadingFinished:(sucBlock)sucBlock CancelLoading:(cancelBlock)cancelBlock LoadingError:(errorBlock)errorBlock
{
    self = [super init];
    if (self) {
        //获取请求的3中状态
        self.sucBlock = sucBlock;
        self.errorBlock = errorBlock;
        self.cancelBlock = cancelBlock;
        [self netWithParameters:dic IndicatorView:view LoadingFinished:sucBlock CancelLoading:cancelBlock LoadingError:errorBlock];
    }
    return nil;
}

-(id)initWithUrl:(NSString *)url Parameters:(NSMutableDictionary *)dic IndicatorView:(UIView *)view LoadingFinished:(sucBlock)sucBlock CancelLoading:(cancelBlock)cancelBlock LoadingError:(errorBlock)errorBlock {
    self = [super init];
    if (self) {
        //获取请求的3中状态
        self.requestUrl = url;
        self.sucBlock = sucBlock;
        self.errorBlock = errorBlock;
        self.cancelBlock = cancelBlock;
        [self netWithParameters:dic IndicatorView:view LoadingFinished:sucBlock CancelLoading:cancelBlock LoadingError:errorBlock];
    }
    return nil;
}

-(void)netWithParameters:(NSMutableDictionary *)dic IndicatorView:(UIView *)view LoadingFinished:(sucBlock)sucBlock CancelLoading:(cancelBlock)cancelBlock LoadingError:(errorBlock)errorBlock {
    _netManager = [AFHTTPSessionManager manager];
    //很重要 不设置这句话 带参数的接口无法获取到
    _netManager.responseSerializer = [AFCompoundResponseSerializer serializer];
    //网络加载是的缓冲处理
    [self loadMaskAcivityView:view];
    
    __block XLBaseAFNetWorking * weakSelf = self;
    //如果地址为空跑出异常
    NSAssert(self.getRequestUrl != nil, @"加载网址为空，不能加载");
    //判断是post还是get请求数据
    switch ([self getRequestMethod]) {
        case XLRequestMethodGet:{
            //get请求
            _dataTask = [_netManager GET:[self getRequestUrl] parameters:dic progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                [weakSelf sucBlockDo:responseObject];
                //                    NSLog(@"数据请求成功,接口为:%@",[weakSelf showUrlWithDictionary:dic]);
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                [weakSelf errorBlockDo:error];
            }];
        }
            break;
        case XLRequestMethodPost:{
            //post请求
            _dataTask = [_netManager POST:[self getRequestUrl] parameters:dic progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                //请求成功后讲传递给自己的子类调用
                [weakSelf sucBlockDo:responseObject];
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                [weakSelf errorBlockDo:error];
            }];
        }
        default:
            break;
    }
}

//打印地址用于测试
-(NSString *)showUrlWithDictionary:(NSDictionary *)dic
{
    //打印地址
    NSString * url = [self getRequestUrl];
    for (NSString * key in dic) {
        url = [url stringByAppendingString:[NSString stringWithFormat:@"&%@=",key]];
        url = [url stringByAppendingString:[dic objectForKey:key]];
    }
    //有问号则加问号
    NSNotFound == [url rangeOfString:@"?"].location ? [url stringByAppendingString:@"&"] :false ;
    return url;
}

//请求成功后走的方法用于传递数据
-(void)sucBlockDo:(id)result
{
    //data转json
    if ([result isKindOfClass:[NSData class]]) {
        self.result = [NSJSONSerialization JSONObjectWithData:result options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:nil];
    }
    else if ([result isKindOfClass:[NSString class]]) {
        NSString * str = (NSString *)result;
        NSData * jsonData = [str dataUsingEncoding:NSUTF8StringEncoding];
        self.result = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
//        NSLog(@"%@",self.result);
    }
    //数据加工处理
    XLBaseNetMode * processresult = [self processResult:self.result];
    if (!processresult) {
//        self.result = result;
    } else {
        if ([processresult isKindOfClass:[XLBaseNetMode class]]) {
            processresult.code = [self.result objectForKey:@"code"];
            processresult.msg = [self.result objectForKey:@"msg"];
            processresult.success = [self.result objectForKey:@"msg"];
            self.result = processresult;
        }
    }
    //执行快语法
    if (self.sucBlock) {
        self.sucBlock(self.result);
    }
    [self loadFinished];
}
//请求出错的时候走的方法
-(void)errorBlockDo:(id)resulte
{
    NSLog(@"请求出错%@",resulte);
    if (self.errorBlock) {
        self.errorBlock(resulte);
    }
    [self loadFinished];
}

//接受到取消下载的通知
-(void)cancelRequest
{
    if (self.cancelBlock) {
         self.cancelBlock();
    }
    [_netManager.operationQueue cancelAllOperations];
    [self loadFinished];
}
//加载完成后的相关处理
-(void)loadFinished
{
    [_activityView stopAnimating];
}

#pragma mark -- 加载数据的时候缓冲图片
-(void)loadMaskAcivityView:(UIView *)superView
{
    if (superView) {
        _activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
        [_activityView startAnimating];
    }
}

-(void)cancel {
    [_dataTask cancel];
}

-(void)dealloc
{
    [_netManager.operationQueue cancelAllOperations];
    [_activityView stopAnimating];
}

#pragma mark 子类重写的
-(id)processResult:(id)result {
    return nil;
}

@end


//*************comet分类
static const void * CometNetWorkingKey = & CometNetWorkingKey; //指针的指针
@implementation XLBaseAFNetWorking (comet)
#pragma mark --comet方式连接
-(id)initCometWithParam:(NSDictionary *)dic LoadingFinished:(sucBlock)sucBlock Error:(errorBlock)errorBlock {
    self = [super init];
    if (self) {
        __weak typeof(self) ws = self;
        //获取请求后的状态
        self.sucBlock = sucBlock;
        self.errorBlock = errorBlock;
        self.cometNet = [CMCometNetWorking CometNetByUrl:[self getRequestUrl] paramDic:dic complete:^(id result) {
            [ws sucBlockDo:result];
        } Error:^(id error) {
            [ws errorBlockDo:error];
        }];
        [self.cometNet resume];
    }
    return self;
}

#pragma mark --方法
-(void)suspend {
    [self.cometNet suspend];
}

-(void)resume {
    [self.cometNet resume];
}

-(void)cancel {
    [self.cometNet cancel];
}

#pragma mark --属性设置
-(void)setCometNet:(CMCometNetWorking *)cometNet {
    objc_setAssociatedObject(self, CometNetWorkingKey, cometNet, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(CMCometNetWorking *)cometNet {
   return objc_getAssociatedObject(self, CometNetWorkingKey);
}
@end



//**************访问本地数据库在加载分类
static const void * dataBaseManager = &dataBaseManager;
@implementation XLBaseAFNetWorking (native)
//如果本地有则用本地的
-(id)initNativeWithParameters:(NSMutableDictionary *)dic IndicatorView:(UIView *)view LoadingFinished:(sucBlock)sucBlock CacelLoading:(cancelBlock)cancelBlock LoadingError:(errorBlock)errorBlock {
    self = [super init];
    if (self) {
        //获取请求的3中状态
        self.sucBlock = sucBlock;
        self.errorBlock = errorBlock;
        self.cancelBlock = cancelBlock;
        [self netNativeWithParameters:dic IndicatorView:view IsMustLoadingFromNet:NO];
    }
    return self;
}
//如果本地有则线用本地的再用网络的
-(id)initNativeAndNetWithParameters:(NSMutableDictionary *)dic IndicatorView:(UIView *)view LoadingFinished:(sucBlock)sucBlock CacelLoading:(cancelBlock)cancelBlock LoadingError:(errorBlock)errorBlock {
    self = [super init];
    if (self) {
        //获取请求的3中状态
        self.sucBlock = sucBlock;
        self.errorBlock = errorBlock;
        self.cancelBlock = cancelBlock;
        [self netNativeWithParameters:dic IndicatorView:view IsMustLoadingFromNet:YES];
    }
    return self;
}

-(void)netNativeWithParameters:(NSMutableDictionary *)dic IndicatorView:(UIView *)view IsMustLoadingFromNet:(BOOL)isMust{
    NSString * requestStr = [[[[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET" URLString:self.getRequestUrl parameters:dic error:nil] URL]absoluteString];
    self.dataBaseManager = [[XLDataBaseManager alloc]initWithDataBaseUrl:nil];
    __weak typeof (self) ws = self;
    //先从本地加载
    [self.dataBaseManager selectValueDataByNetTableWithUrlStr:requestStr CompleteBlock:^(NSString *data) {
        if (data) {
            [ws sucBlockDo:data];
            if (isMust) {
                //加载本地后再加载一次网络
                [ws getMessageFromNetWithParameters:dic IndicatorView:view Url:requestStr];
            }
        }
        else {
            //如果没有数据则发起网络请求
            [ws getMessageFromNetWithParameters:dic IndicatorView:view Url:requestStr];
        }
    }];
}
//网络获取数据且存储到本地
-(void)getMessageFromNetWithParameters:(NSMutableDictionary *)dic IndicatorView:(UIView *)view Url:(NSString *)url{
    _netManager = [AFHTTPSessionManager manager];
    //很重要 不设置这句话 带参数的接口无法获取到
    _netManager.responseSerializer = [AFCompoundResponseSerializer serializer];
    //网络加载是的缓冲处理
    [self loadMaskAcivityView:view];
    
    __block XLBaseAFNetWorking * weakSelf = self;
    //如果地址为空跑出异常
    NSAssert(self.getRequestUrl != nil, @"加载网址为空，不能加载");
    //判断是post还是get请求数据
    switch ([self getRequestMethod]) {
        case XLRequestMethodGet:{
            //get请求
            _dataTask = [_netManager GET:[self getRequestUrl] parameters:dic progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                if ([responseObject isKindOfClass:[NSData class]]) {
                    //存储网络加载好的数据
//                    NSString * dataStr = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:nil];
                    NSString * dataStr = [[NSString alloc]initWithData:responseObject encoding:NSUTF8StringEncoding];
                    [self.dataBaseManager insertDataToNetTableWithUrlStr:url Value:dataStr CompleteBlock:nil];
                }
                [weakSelf sucBlockDo:responseObject];
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                [weakSelf errorBlockDo:error];
            }];
        }
            break;
        case XLRequestMethodPost:{
            //post请求
            _dataTask = [_netManager POST:[self getRequestUrl] parameters:dic progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                //请求成功后讲传递给自己的子类调用
                [weakSelf sucBlockDo:responseObject];
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                [weakSelf errorBlockDo:error];
            }];
        }
        default:
            break;
    }
}

#pragma mark --属性
-(void)setDataBaseManager:(XLDataBaseManager *)manager {
    objc_setAssociatedObject(self, dataBaseManager, manager, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(XLDataBaseManager *)dataBaseManager {
    return objc_getAssociatedObject(self, dataBaseManager);
}

@end
